package com.bj58.groupbuy.action.threads;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import com.bj58.groupbuy.action.model.IRReport;
import com.bj58.groupbuy.action.model.IRSubMailVo;
import com.bj58.groupbuy.action.service.IRReportService;
import com.bj58.groupbuy.action.service.IRSubMailService;
import com.bj58.groupbuy.action.service.IntReportMainService;
import com.bj58.groupbuy.action.util.DateUtil;
import com.bj58.groupbuy.action.util.ExcelUtilNew;
import com.bj58.groupbuy.action.util.FileUtil;
import com.bj58.groupbuy.action.util.MailUtil;
import com.bj58.groupbuy.action.util.MyPathUtil;
import com.bj58.groupbuy.action.util.ScfUtil;
import com.bj58.groupbuy.action.util.VelocityTools;
import com.bj58.groupbuy.action.util.ZipUtil;
import com.bj58.groupbuy.service.locator.ServiceLocator;
import com.bj58.groupbuy.util.PathUtil;
import com.bj58.groupbuy.wf.page.Paginate;

public class ReportSubEmailThread  extends Thread{
	private IRReportService iRReportService = ServiceLocator.get(IRReportService.class);
	private IntReportMainService intReportMainService = ServiceLocator.get(IntReportMainService.class);
	private IRSubMailService iRSubMailService = ServiceLocator.get(IRSubMailService.class);
	
	public static AtomicInteger threadDoneCount = new AtomicInteger();
	
	private IRSubMailVo irsm;
	
	public ReportSubEmailThread(IRSubMailVo irsm){
		this.irsm = irsm;
	}
	
	public void run(){
		try {
			System.out.println("Thead  "+this.getId()+" begin to deal subMail ,ID  is" + irsm.getId());
			int result = sendSubMail(irsm);
			if(result == 2){
				irsm.setModTime(DateUtil.getStringDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
				iRSubMailService.updateVo(irsm);
			}
			System.out.println("Thead  "+this.getId()+" is end ");
			threadDoneCount.getAndIncrement(); //线程完成则在原子计数器上+1
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	
	/**报表订阅邮件发送
	 * @param vo
	 * @return  报表订阅邮件发送结果 	0 : 邮件发送失败  1：数据集为空   2：发送成功
	 */
	@SuppressWarnings("static-access")
	private int sendSubMail(IRSubMailVo vo){
		try {
			/**step 1.根据订阅的发送频率替换查询条件中的日期段参数
			 *  step 2.查询全部数据
			 *  step 3.判断数据结果内容大小，读取模板，选择以正文/EXCEL压缩附件发送；若超大则提示过大，发送提示内容。
			 */
			//step 1
			StringBuffer searchCondition=new StringBuffer();
			String condition = vo.getSearchCondition();
			String hasComp="";
			boolean hasDayRatio=false,hasWeekRatio=false;
			int dayRatio=vo.getDayRatio(); //环同比标志:1包含，0不包含
			int weekRatio=vo.getWeekRatio();
			StringBuffer specialValues=new StringBuffer();
			String specialValue=vo.getSearchSpeValue();
			//日期列名称,从specialValue中获取
			String dateCol=specialValue.substring(specialValue.lastIndexOf(":")+1,specialValue.length()-1).trim();;
			//发送频率  day = 每日发送  week = 每周发送(默认周1)  
			//W1/3/5 = 自定义每周1/3/5发送  D10/20/30 自定义每月10、20、30号发送 月末需判定
			String sendFre = vo.getSendFre(); 
			String changeBeginDate = ""; //开始日期
			String changeEndDate = ""; //结束日期
			String startDate="";
			String endDate="";
			Date nowDate=new Date();
//			nowDate=DateUtil.strToDate("2014-04-14", "yyyy-MM-dd");
			if("day".equals(sendFre)){
				//需要获得结果的起止日期
				changeBeginDate = changeEndDate = DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 1),"yyyy-MM-dd");
				//实际查询起止日期
				startDate=endDate=DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 1),"yyyy-MM-dd");
				searchCondition.append(" and "+dateCol+" in('"+changeBeginDate+"'");
				//前一天
				if(dayRatio==1){
					startDate=DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 2),"yyyy-MM-dd");
					searchCondition.append(",'"+startDate+"'");
				}
				//上周
				if(weekRatio==1){
					startDate=DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 8),"yyyy-MM-dd");
					searchCondition.append(",'"+startDate+"'");
				}
				searchCondition.append(") ");
			}else if("week".equals(sendFre)){
				//上一周  周1-周日
				changeBeginDate =DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 7),"yyyy-MM-dd");
				changeEndDate =DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 1),"yyyy-MM-dd");
				//若含有同环比，时间范围需扩大
				if(weekRatio==1){
					startDate = DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 14),"yyyy-MM-dd");
					endDate = DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 1),"yyyy-MM-dd");
				}else if(dayRatio==1){
					startDate =DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 8),"yyyy-MM-dd");
					endDate =DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 1),"yyyy-MM-dd");
				}else{
					startDate =DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 7),"yyyy-MM-dd");
					endDate =DateUtil.getStringDate(DateUtil.getDateBefore(nowDate, 1),"yyyy-MM-dd");
				}
				searchCondition.append(" and "+dateCol+">='"+startDate+"'");
				searchCondition.append(" and "+dateCol+"<='"+endDate+"' ");
			}
			searchCondition.append(condition);		
			specialValues.append("startDate:"+startDate+";");
			specialValues.append("endDate:"+endDate+";");
			specialValues.append("dateName:"+dateCol+";");
			//step 2
			IRReport irReport = iRReportService.getById(vo.getReportId());
			List<String> cols = new ArrayList<String>(); //查询字段项 -英文
			String gbs[] = null;
			if(!"".equals(vo.getSearchGroupBy())){//groupBy占位
				gbs=vo.getSearchGroupBy().split(",");
				cols.add("groupBy");
			}
			for(String col : vo.getSearchCols().split("&")){
				if(!"".equals(col)){
					cols.add(col);
				}
			}
			
			List<String> titleList = new ArrayList<String>(); //查询字段项 - 中文 表格TITLE
			for(String title : vo.getSearchTitles().split("&")){
				if(!"".equals(title)){
					titleList.add(title);
				}
			}
			
			Paginate<String> pList = intReportMainService.IRsearchValues(irReport, searchCondition.toString(), cols,null, vo.getSearchOrderBy(), vo.getSearchGroupBy(), 20, -1,specialValues.toString(),1);
			//step 3
				//收件人地址
			String[] emailAdds = vo.getSendEmail().split("/");
			//标题
			String titleDates = " ";
			if(changeBeginDate.equals(changeEndDate)){
				titleDates = changeBeginDate;
			}else{
				titleDates = " from "+changeBeginDate +" to " + changeEndDate;
			}
			String emailTitle= "商业数据分析系统 - 报表订阅邮件 - "+vo.getReportName()+titleDates;
			//正文内容
			String content = "表格过大，邮件正文只支持最大 200行 * 15列的表格，请参考附件。";
			//附件地址
			ArrayList<String>  attachedFileList =  new ArrayList<String>();
			// 内容及
			int maxShowRows = 200; // 正文最大数据行
			int maxShowCols = 30; // 正文最大数据列
			int maxSendRows = 1000000; // 发送最大的数据行
			// 数据量不超标
			if(pList.getItems().size() < maxSendRows){//写EXCEL保存 并压缩
				SXSSFWorkbook wwb = null;
				HashMap<String, String> keyValue = new HashMap<String, String>();
				List<String> toSendItems = pList.getItems(); // 要发送的结果
				if (dayRatio == 1 || weekRatio == 1){
					toSendItems = new ArrayList<String>();
					// 含同环比
					if (dayRatio == 1) {
						hasComp += "dayRatio";
						hasDayRatio = true;
					}
					if (weekRatio == 1) {
						hasComp += ",weekRatio";
						hasWeekRatio = true;
					}
					List<String> items = pList.getItems(); // 获得总结果集
					for (String recode : items) { // 对每一条记录提取维度值，放入对应的Map中
						StringBuilder key = new StringBuilder();
						String cells[] = recode.split(";", gbs.length + 1);
						for (int i = 0; i < gbs.length; i++) { // 维度
							key.append(cells[i].split(",")[0]);
							if (i + 1 < gbs.length)
								key.append("_");
						}
						String date = cells[0].split(",")[0];// 日期
						if (date.compareTo(changeBeginDate) >= 0&& date.compareTo(changeEndDate) <= 0)
							toSendItems.add(recode);
						keyValue.put(key.toString(), cells[gbs.length]);
					}
				}
				if (null == toSendItems || toSendItems.isEmpty()) { // 要发送的数据集为空
					System.out.println("Send ReportSubEmail Fail! The  Datas is null, The SubMail  ID is "+ vo.getId());
					MailUtil.javaMailSend("订阅邮件数据为空", "订阅ID为" + vo.getId(),"huangliang@58.com", null);
					return 1;
				}
				// 文件夹路径
				String dirPath = PathUtil.getWFNamespaceFolder()+ "/ReportSubMail" + "/SubMail-" + vo.getId() + "-"+ titleDates;
				String excelPath = dirPath + "/SubMail-" + vo.getId() + "-"+ titleDates + ".xlsx";
				File file = new File(dirPath);
				if (file.exists() && file.isDirectory()) {
					FileUtil.deleteDirectory(dirPath);
				}
				file.mkdirs();
				int statgbsindex=0;
				if(null !=gbs)
				{
					for (int i = 0; i < gbs.length; i++) { // 日期维度所在位置
						if (gbs[i].equals("stat_date")||gbs[i].equals("statDate")||gbs[i].equals("vDate")) {
							statgbsindex=i;
							break;
						}
					}
				}
				if ((dayRatio == 1 || weekRatio == 1) && gbs != null){
					wwb = ExcelUtilNew.writeExcelCommonWithRatioSync(vo.getReportName() + titleDates, null, titleList,toSendItems, keyValue, gbs.length, excelPath,dayRatio == 1 ? true : false, weekRatio == 1 ? true:false,statgbsindex);
				}else{
					int gbLength = 0 ;
					if(null != gbs ){
						gbLength = gbs.length;
					}
					wwb = ExcelUtilNew.writeExcelCommonWithRatioSync(vo.getReportName()+ titleDates, null, titleList, toSendItems,null,gbLength,excelPath,false,false,statgbsindex);
				}
					
					
				if(wwb==null){
					FileUtil.deleteDirectory(dirPath);
					return 1;
				}
				else{
					FileOutputStream os = new FileOutputStream(excelPath);
					wwb.write(os);
					os.close();
				}
				// 将整个文件夹压缩
				ZipUtil zip = new ZipUtil();
				String zipPath = dirPath + ".zip";
				FileUtil.deleteFile(zipPath);
				zip.createZip(zipPath, dirPath);
				attachedFileList.add(zipPath);

				// 正文不超大则渲染成表格
				if (toSendItems.size() <= maxShowRows&& cols.size() <= maxShowCols) {
					String templateSelectOnePath = PathUtil.getWFNamespaceFolder()+ "/emailtemp/reportSubMail.html";// 订阅邮件模板
					Map<String, Object> conMap = new HashMap<String, Object>();
					conMap.put("hasComp", hasComp);
					if(null != gbs){
						conMap.put("gbCount",gbs.length);
					}
					conMap.put("gbValueMap", keyValue);
					conMap.put("dayRatio",hasDayRatio);
					conMap.put("weekRatio",hasWeekRatio);
					conMap.put("rsList", toSendItems);
					conMap.put("titleList", titleList);
					conMap.put("reportName", vo.getReportName() + titleDates);
					conMap.put("statgrpindex", statgbsindex);
					String main = MyPathUtil.getTemByPath(templateSelectOnePath);
					content = VelocityTools.render(main, conMap);
				}
			} else {
				content = "您订阅的报表数据量过大，请登录商业数据分析系统(http://bi.t.58.com)修改查询条件并重新订阅！";
			}
			// 发送
			for (String address : emailAdds) {
				address = address.trim();
				int sendResult = MailUtil.javaMailSend(emailTitle, content,address, attachedFileList);
				if (sendResult == 1) {
					System.out.println("Send ReportSubEmail success! The E-mail ad  is "+ address+ ", The SubMail  ID is "+ vo.getId());
				} else {
					System.out.println("Send ReportSubEmail fail! The E-mail ad  is "+ address+ ", The SubMail  ID is "+ vo.getId());
					MailUtil.javaMailSend("订阅邮件发送失败", "订阅ID为" + vo.getId()+ ",收件人地址为" + address, "huangliang@58.com", null);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			MailUtil.javaMailSend("订阅邮件发送程序报错", "订阅ID为" + vo.getId(),
					"huangliang@58.com", null);
			return 0;
		}
		return 2;
	}
	
	
	public static void main(String[] args) {
		try {
			IRSubMailService iRSubMailService = ServiceLocator.get(IRSubMailService.class);
			ScfUtil.initSCF();//SCF初始化 扫包
			
//			int maxPoolSize = 2; //线程池中最大线程数
//			ExecutorService pool = Executors. newFixedThreadPool(maxPoolSize);
			
			List<IRSubMailVo> smList = iRSubMailService.getAllToSendList();//所有状态正常的订阅
			//List<IRSubMailVo> smList = iRSubMailService.getListByUserId(1585);//所有状态正常wo的订阅
			List<IRSubMailVo> sendList = new ArrayList<IRSubMailVo>(); //待发送的订阅  
			
			for(IRSubMailVo vo : smList){
				String modTime = vo.getModTime();
				//去掉今日已发送过的
				if(("".equals(modTime)  || null == modTime || !modTime.contains(DateUtil.getStringDate(new Date(), "yyyy-MM-dd")))&&(vo.getState()==1)){
					//如果是周订阅 判断今日是否周1，否则不发送
					if("week".equals(vo.getSendFre())){
						int wod = DateUtil.getWeekOfDate(new Date());
						if(wod == 1){
							sendList.add(vo);
						}
					}else if("day".equals(vo.getSendFre())){
						sendList.add(vo);
					}
				}
			}
			
			
			if(null == sendList || sendList.isEmpty()){
				System.out.println("No sub mail have to send !");
			}else{
				int corePoolSize = Runtime.getRuntime().availableProcessors();//CPU个数
//				int maximumPoolSize = 2;//线程池中最大线程数
				long keepAliveTime = 10; //线程活动保持时间
				LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(sendList.size()); //线程队列
				ThreadPoolExecutor  pool = new ThreadPoolExecutor(corePoolSize/2, corePoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
//				ExecutorService pool=Executors.newCachedThreadPool();
				for(IRSubMailVo vo : sendList){
					Thread  thread = new ReportSubEmailThread(vo);
					pool.submit(thread);
				}
				while(true){
					if(ReportSubEmailThread.threadDoneCount.get() == sendList.size()){
						pool.shutdown();
						System.out.println("All sub mail has done!");
						break;
					}
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			System.exit(0);
		}
	
	}
}
